package repository

import (
	"fitness/go-admin/internal/model"
	"time"

	"gorm.io/gorm"
)

// ChatRepository 客服聊天数据访问层
type ChatRepository struct {
	db *gorm.DB
}

// NewChatRepository 创建客服聊天仓库
func NewChatRepository(db *gorm.DB) *ChatRepository {
	return &ChatRepository{db: db}
}

// ==================== ChatSession 会话相关 ====================

// CreateSession 创建会话
func (r *ChatRepository) CreateSession(session *model.ChatSession) error {
	return r.db.Create(session).Error
}

// GetSessionByID 根据ID获取会话（完善错误处理）
func (r *ChatRepository) GetSessionByID(id uint) (*model.ChatSession, error) {
	var session model.ChatSession
	err := r.db.Preload("Member").Preload("Staff").Preload("LastMessage").
		First(&session, id).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, gorm.ErrRecordNotFound // 明确返回记录不存在错误
		}
		return nil, err // 其他数据库错误
	}
	return &session, nil
}

// GetUserSessions 获取用户的会话列表
func (r *ChatRepository) GetUserSessions(userID uint, status string, page, pageSize int) ([]model.ChatSession, int64, error) {
	var sessions []model.ChatSession
	var total int64

	query := r.db.Model(&model.ChatSession{}).
		Where("member_id = ? OR staff_id = ?", userID, userID)

	if status != "" {
		query = query.Where("status = ?", status)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (page - 1) * pageSize
	err := query.Order("last_message_at DESC NULLS LAST, created_at DESC").
		Preload("Member").Preload("Staff").Preload("LastMessage").
		Offset(offset).Limit(pageSize).
		Find(&sessions).Error

	return sessions, total, err
}

// GetStaffActiveSessions 获取客服的活跃会话列表
func (r *ChatRepository) GetStaffActiveSessions(staffID uint) ([]model.ChatSession, error) {
	var sessions []model.ChatSession
	err := r.db.Where("staff_id = ? AND status = ?", staffID, "ACTIVE").
		Order("last_message_at DESC").
		Preload("Member").Preload("LastMessage").
		Find(&sessions).Error
	return sessions, err
}

// GetWaitingSessions 获取等待中的会话列表（未分配客服）
func (r *ChatRepository) GetWaitingSessions() ([]model.ChatSession, error) {
	var sessions []model.ChatSession
	err := r.db.Where("status = ?", "WAITING").
		Order("created_at ASC").
		Preload("Member").
		Find(&sessions).Error
	return sessions, err
}

// UpdateSession 更新会话
func (r *ChatRepository) UpdateSession(session *model.ChatSession) error {
	return r.db.Save(session).Error
}

// UpdateSessionStatus 更新会话状态
func (r *ChatRepository) UpdateSessionStatus(sessionID uint, status string) error {
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		Update("status", status).Error
}

// AssignStaff 分配客服
func (r *ChatRepository) AssignStaff(sessionID, staffID uint) error {
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		Updates(map[string]interface{}{
			"staff_id": staffID,
			"status":   "ACTIVE",
		}).Error
}

// CloseSession 关闭会话
func (r *ChatRepository) CloseSession(sessionID, closedBy uint, rating *int, comment string) error {
	now := time.Now()
	updates := map[string]interface{}{
		"status":    "CLOSED",
		"closed_at": now,
		"closed_by": closedBy,
	}
	if rating != nil {
		updates["rating"] = *rating
		updates["rating_comment"] = comment
	}
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		Updates(updates).Error
}

// UpdateSessionLastMessage 更新会话最后消息
func (r *ChatRepository) UpdateSessionLastMessage(sessionID, messageID uint) error {
	now := time.Now()
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		Updates(map[string]interface{}{
			"last_message_id": messageID,
			"last_message_at": now,
		}).Error
}

// CloseInactiveSessions 批量关闭超时的会话
func (r *ChatRepository) CloseInactiveSessions(cutoffTime time.Time) (int64, error) {
	now := time.Now()
	result := r.db.Model(&model.ChatSession{}).
		Where("status IN (?)", []string{"WAITING", "ACTIVE"}).
		Where("last_message_at < ? OR (last_message_at IS NULL AND created_at < ?)", cutoffTime, cutoffTime).
		Updates(map[string]interface{}{
			"status":    "CLOSED",
			"closed_at": now,
			"closed_by": 0, // 系统自动关闭
		})

	if result.Error != nil {
		return 0, result.Error
	}

	return result.RowsAffected, nil
}

// SearchMessages 搜索消息
func (r *ChatRepository) SearchMessages(sessionID uint, keyword string, page, pageSize int) ([]model.ChatMessage, int64, error) {
	var messages []model.ChatMessage
	var total int64

	query := r.db.Model(&model.ChatMessage{}).
		Where("session_id = ?", sessionID).
		Where("is_recalled = ?", false)

	// 搜索关键词（在文本内容或文件名中）
	if keyword != "" {
		query = query.Where("(content LIKE ? OR file_name LIKE ?)", "%"+keyword+"%", "%"+keyword+"%")
	}

	// 计数
	query.Count(&total)

	// 分页查询
	offset := (page - 1) * pageSize
	err := query.Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Preload("Sender").
		Find(&messages).Error

	return messages, total, err
}

// TransferSession 转接会话
func (r *ChatRepository) TransferSession(sessionID, fromStaffID, toStaffID uint) error {
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		Where("staff_id = ?", fromStaffID).
		Update("staff_id", toStaffID).Error
}

// IncrementUnreadCount 增加未读数
func (r *ChatRepository) IncrementUnreadCount(sessionID uint, isStaff bool) error {
	field := "unread_count"
	if isStaff {
		field = "staff_unread_count"
	}
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		UpdateColumn(field, gorm.Expr(field+" + ?", 1)).Error
}

// ClearUnreadCount 清空未读数
func (r *ChatRepository) ClearUnreadCount(sessionID uint, isStaff bool) error {
	field := "unread_count"
	if isStaff {
		field = "staff_unread_count"
	}
	return r.db.Model(&model.ChatSession{}).
		Where("id = ?", sessionID).
		Update(field, 0).Error
}

// ==================== ChatMessage 消息相关 ====================

// CreateMessage 创建消息（不使用事务，已弃用，请使用 CreateMessageWithTransaction）
func (r *ChatRepository) CreateMessage(message *model.ChatMessage) error {
	return r.db.Create(message).Error
}

// CreateMessageWithTransaction 创建消息并更新会话信息（使用事务确保数据一致性）
func (r *ChatRepository) CreateMessageWithTransaction(message *model.ChatMessage) error {
	return r.db.Transaction(func(tx *gorm.DB) error {
		// 1. 创建消息
		if err := tx.Create(message).Error; err != nil {
			return err
		}

		// 2. 更新会话的最后消息信息
		updates := map[string]interface{}{
			"last_message_id": message.ID,
			"last_message_at": message.CreatedAt,
		}

		// 3. 根据发送者类型增加对应的未读数
		if message.SenderType == "MEMBER" {
			// 会员发送的消息，客服未读数 +1
			updates["staff_unread_count"] = gorm.Expr("staff_unread_count + ?", 1)
		} else if message.SenderType == "STAFF" {
			// 客服发送的消息，会员未读数 +1
			updates["unread_count"] = gorm.Expr("unread_count + ?", 1)
		}

		if err := tx.Model(&model.ChatSession{}).
			Where("id = ?", message.SessionID).
			Updates(updates).Error; err != nil {
			return err
		}

		return nil
	})
}

// GetMessageByID 根据ID获取消息
func (r *ChatRepository) GetMessageByID(id uint) (*model.ChatMessage, error) {
	var message model.ChatMessage
	err := r.db.Preload("Sender").First(&message, id).Error
	if err != nil {
		return nil, err
	}
	return &message, nil
}

// GetSessionMessages 获取会话的消息列表
func (r *ChatRepository) GetSessionMessages(sessionID uint, page, pageSize int, beforeID uint) ([]model.ChatMessage, int64, error) {
	var messages []model.ChatMessage
	var total int64

	query := r.db.Model(&model.ChatMessage{}).Where("session_id = ?", sessionID)

	// 如果指定了beforeID，获取该消息之前的消息（用于向上滚动加载）
	if beforeID > 0 {
		query = query.Where("id < ?", beforeID)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询（按时间倒序）
	offset := (page - 1) * pageSize
	err := query.Order("created_at DESC").
		Preload("Sender").
		Offset(offset).Limit(pageSize).
		Find(&messages).Error

	return messages, total, err
}

// GetUnreadMessages 获取未读消息
func (r *ChatRepository) GetUnreadMessages(sessionID uint, excludeSenderID uint) ([]model.ChatMessage, error) {
	var messages []model.ChatMessage
	err := r.db.Where("session_id = ? AND sender_id != ? AND is_read = ?", sessionID, excludeSenderID, false).
		Order("created_at ASC").
		Preload("Sender").
		Find(&messages).Error
	return messages, err
}

// GetUnreadCount 获取未读消息数量
func (r *ChatRepository) GetUnreadCount(sessionID uint, excludeSenderID uint) (int64, error) {
	var count int64
	err := r.db.Model(&model.ChatMessage{}).
		Where("session_id = ? AND sender_id != ? AND is_read = ?", sessionID, excludeSenderID, false).
		Count(&count).Error
	return count, err
}

// MarkMessagesAsRead 标记消息为已读
func (r *ChatRepository) MarkMessagesAsRead(messageIDs []uint) error {
	now := time.Now()
	return r.db.Model(&model.ChatMessage{}).
		Where("id IN ?", messageIDs).
		Updates(map[string]interface{}{
			"is_read": true,
			"read_at": now,
		}).Error
}

// MarkSessionMessagesAsRead 标记会话的所有消息为已读
func (r *ChatRepository) MarkSessionMessagesAsRead(sessionID uint, excludeSenderID uint) error {
	now := time.Now()
	return r.db.Model(&model.ChatMessage{}).
		Where("session_id = ? AND sender_id != ? AND is_read = ?", sessionID, excludeSenderID, false).
		Updates(map[string]interface{}{
			"is_read": true,
			"read_at": now,
		}).Error
}

// RecallMessage 撤回消息
func (r *ChatRepository) RecallMessage(messageID uint) error {
	now := time.Now()
	return r.db.Model(&model.ChatMessage{}).
		Where("id = ?", messageID).
		Updates(map[string]interface{}{
			"is_recalled": true,
			"recalled_at": now,
		}).Error
}

// GetMessagesBySenderInSession 获取指定用户在会话中发送的消息
func (r *ChatRepository) GetMessagesBySenderInSession(sessionID, senderID uint) ([]model.ChatMessage, error) {
	var messages []model.ChatMessage
	err := r.db.Where("session_id = ? AND sender_id = ?", sessionID, senderID).
		Order("created_at DESC").
		Find(&messages).Error
	return messages, err
}

// ==================== 统计相关 ====================

// GetUserTotalUnreadCount 获取用户所有会话的未读消息总数
func (r *ChatRepository) GetUserTotalUnreadCount(userID uint) (int64, error) {
	var totalUnread int64

	// 查询用户作为会员的会话未读数
	var memberUnread int64
	if err := r.db.Model(&model.ChatSession{}).
		Where("member_id = ?", userID).
		Select("COALESCE(SUM(unread_count), 0)").
		Scan(&memberUnread).Error; err != nil {
		return 0, err
	}

	// 查询用户作为客服的会话未读数
	var staffUnread int64
	if err := r.db.Model(&model.ChatSession{}).
		Where("staff_id = ?", userID).
		Select("COALESCE(SUM(staff_unread_count), 0)").
		Scan(&staffUnread).Error; err != nil {
		return 0, err
	}

	totalUnread = memberUnread + staffUnread
	return totalUnread, nil
}

// GetSessionStatistics 获取会话统计信息
func (r *ChatRepository) GetSessionStatistics(sessionID uint) (map[string]interface{}, error) {
	var totalMessages int64
	var unreadMessages int64

	// 总消息数
	if err := r.db.Model(&model.ChatMessage{}).
		Where("session_id = ?", sessionID).
		Count(&totalMessages).Error; err != nil {
		return nil, err
	}

	// 未读消息数
	if err := r.db.Model(&model.ChatMessage{}).
		Where("session_id = ? AND is_read = ?", sessionID, false).
		Count(&unreadMessages).Error; err != nil {
		return nil, err
	}

	return map[string]interface{}{
		"total_messages":  totalMessages,
		"unread_messages": unreadMessages,
	}, nil
}
